using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Gko.Utils
{
	public static class SynchronizationContextExtensions
	{
		public static Background CreateBackground(this SynchronizationContext syncContext)
		{
			return new Background(syncContext);
		}

		public static void BeginInvoke<TResult>(this SynchronizationContext syncContext, Func<TResult> func, Action<TResult> resultHandler)
		{
			syncContext.BeginInvoke(() => resultHandler(func()));
		}

		public static void BeginInvoke<T, TResult>(this SynchronizationContext syncContext, Func<T, TResult> func, Action<TResult> resultHandler, T arg)
		{
			syncContext.BeginInvoke(func.Partial(arg), resultHandler);
		}

		public static void BeginInvoke<T, TResult>(this SynchronizationContext syncContext, Func<TResult> func, Action<T, TResult> resultHandler, T arg)
		{
			syncContext.BeginInvoke(func, resultHandler.Partial(arg));
		}

		public static void BeginInvoke<T, TResult>(this SynchronizationContext syncContext, Func<T, TResult> func, Action<T, TResult> resultHandler, T arg)
		{
			syncContext.BeginInvoke(func.Partial(arg), resultHandler.Partial(arg));
		}

		public static void BeginInvoke<T, TResult>(this SynchronizationContext syncContext, Func<T, TResult> func, Action<TResult> resultHandler, Func<T> arg)
		{
			syncContext.BeginInvoke(() => resultHandler(func(arg())));
		}

		public static void BeginInvoke<T, TResult>(this SynchronizationContext syncContext, Func<TResult> func, Action<T, TResult> resultHandler, Func<T> arg)
		{
			syncContext.BeginInvoke(() => resultHandler(arg(), func()));
		}

		public static void BeginInvoke<T, TResult>(this SynchronizationContext syncContext, Func<T, TResult> func, Action<T, TResult> resultHandler, Func<T> arg)
		{
			syncContext.BeginInvoke(() => {
			                        	var a = arg();
			                        	resultHandler(a, func(a));
			                        });
		}
			
		public static void BeginInvoke(this SynchronizationContext syncContext, Action action)
		{
			syncContext.Post(p => action(), null);
		}
	
		public static void BeginInvoke<T>(this SynchronizationContext syncContext, Action<T> action, T arg)
		{
			syncContext.Post(p => action((T)p), arg);
		}
	
		public static void BeginInvoke<T>(this SynchronizationContext syncContext, Action<T> action, Func<T> arg)
		{
			syncContext.BeginInvoke(() => action(arg()));
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1")]
		public static void BeginInvoke<T1, T2>(this SynchronizationContext syncContext, Action<T1, T2> action, T1 arg1, T2 arg2)
		{
			syncContext.BeginInvoke(action.Partial(arg1), arg2);
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "3"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1")]
		public static void BeginInvoke<T1, T2, T3>(this SynchronizationContext syncContext, Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
		{
			syncContext.BeginInvoke(action.Partial(arg1), arg2, arg3);
		}
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "4"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "3"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1")]
		public static void BeginInvoke<T1, T2, T3, T4>(this SynchronizationContext syncContext, Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
		{
			syncContext.BeginInvoke(action.Partial(arg1), arg2, arg3, arg4);
		}

		public static TResult Invoke<TResult>(this SynchronizationContext syncContext, Func<TResult> func)
		{
			var result = default(TResult);
			syncContext.Send(o => result = func(), null);
			return result;
		}

		public static TResult Invoke<T, TResult>(this SynchronizationContext syncContext, Func<T, TResult> func, T arg)
		{
			return syncContext.Invoke(func.Partial(arg));
		}

		public static TResult Invoke<T, TResult>(this SynchronizationContext syncContext, Func<T, TResult> func, Func<T> arg)
		{
			return syncContext.Invoke(() => func(arg()));
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1")]
		public static TResult Invoke<T1, T2, TResult>(this SynchronizationContext syncContext, Func<T1, T2, TResult> func, T1 arg1, T2 arg2)
		{
			return syncContext.Invoke(func.Partial(arg1), arg2);
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "3"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1")]
		public static TResult Invoke<T1, T2, T3, TResult>(this SynchronizationContext syncContext, Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3)
		{
			return syncContext.Invoke(func.Partial(arg1), arg2, arg3);
		}

		public static void Invoke(this SynchronizationContext syncContext, Action action)
		{
			syncContext.Send(p => action(), null);
		}

		public static void Invoke<T>(this SynchronizationContext syncContext, Action<T> action, T arg)
		{
			syncContext.Send(p => action((T)p), arg);
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1")]
		public static void Invoke<T1, T2>(this SynchronizationContext syncContext, Action<T1, T2> action, T1 arg1, T2 arg2)
		{
			syncContext.Invoke(action.Partial(arg1), arg2);
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "3"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1")]
		public static void Invoke<T1, T2, T3>(this SynchronizationContext syncContext, Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
		{
			syncContext.Invoke(action.Partial(arg1), arg2, arg3);
		}
	}
}